#include "adaptvision.h"
#include "genericncctemplatematching.h"
#include "edgefitting.h"
#include "circleedgefitting.h"
#include "commonutils.h"
#include "glueinspection.h"

AdaptVision::AdaptVision()
{
}

bool AdaptVision::checkDongle()
{
    try {
        atl::Array< avl::Point2D > g_constData1;
        g_constData1.Reset(2);
        g_constData1[0] = avl::Point2D(0.0f, 0.0f);
        g_constData1[1] = avl::Point2D(399.0f, 412.0f);
        avl::Path path1;
        atl::Array< avl::Point2D > point2DArray1;

        avs::AvsFilter_MakePath( g_constData1, false, path1 );

        avs::AvsFilter_AccessPath( path1, point2DArray1, atl::Dummy<bool>().Get() );
    } catch (const atl::Error& error) {
        qWarning("Throw Error: %s", error.Message());
        return false;
    }
    return true;
}

bool AdaptVision::performPr(QImage &image, QString prName, PrType prType, double objectScore, PRResultImageInfo &resultImageInfo, PRResultStruct &prResult, int roiRowIndex, int roiColIndex, QVariantMap args)
{
    QImage resultImage;
    qInfo("Perform PR: %s", prName.toStdString().c_str());
    resultImageInfo.prType = prType;
    for(QVariantMap::const_iterator iter = args.begin(); iter != args.end(); ++iter) {
      qDebug() << iter.key() << iter.value();
    }
    if (prType == PrType::Generic_NCC_Template_Matching) {
        qInfo("Going to perform NCC Template Mataching");
        return GenericNCCTemplateMatching::PR_Generic_NCC_Template_Matching(image, resultImage, prName, prResult, objectScore, true, resultImageInfo);
    } else if (prType == PrType::Edge_Template_Matching) {
        qInfo("Going to perform edge fitting");
        args["col"] = roiColIndex;
        args["objectScore"] = objectScore;
        return EdgeFitting::PR_Edge_Fitting(image, resultImage, prName, prResult, args, resultImageInfo);
    } else if (prType == PrType::Circle_Edge_Template_Matching) {
        qInfo("Going to perform circle edge fitting");
        return CircleEdgeFitting::PR_Circle_Edge_Fitting(image, resultImage, prName, prResult, args,resultImageInfo);
    }
    qWarning("Invalid input pr type");
    return false;
}

QVector<QPointF> AdaptVision::readDispensePath(QString filename)
{
    QVector<QPointF> result;
    atl::String g_constData1 = filename.toStdString().c_str();
    atl::String g_constData2 = L"PathArray";

    atl::Array< avl::Path > pathArray1;
    atl::Array< avl::Point2D > point2DArray1;

    if (!checkFileExist(filename)) return result;

    avs::LoadObject< atl::Array< avl::Path > >( g_constData1, avl::StreamMode::Binary, g_constData2, pathArray1 );

    try {
        for( int i = 0; i < pathArray1.Size(); ++i )
        {
            avs::AvsFilter_AccessPath( pathArray1[i], point2DArray1, atl::Dummy<bool>().Get() );
            for ( int j = 0; j < point2DArray1.Size(); ++j)
            {
                float x = point2DArray1[j].x;
                float y = point2DArray1[j].y;
                result.push_back(QPoint(x, y));
            }
        }
    } catch (const atl::Error& error) {
        qWarning("Throw Error: %s", error.Message());
        return result;
    }
    return result;
}

//bool AdaptVision::glueCheck(QImage &imageBefore, QImage &imageAfter, double resoultion, QImage &resultImage, double &outMinGlueWidth, double &outMaxGlueWidth, double &outMaxAvgGlueWidth)
//{
//    double inMinWidth = 0, inMaxWidth = 0, inAvgWidth = 0;
//    return glueInspection::glueCheck(imageBefore, imageAfter, resoultion, resultImage, inMinWidth, inMaxWidth, inAvgWidth, outMinGlueWidth, outMaxGlueWidth, outMaxAvgGlueWidth);
//}

void AdaptVision::drawResultImage(QImage &image, PRResultImageInfo &resultImageInfo){
    qInfo("Draw Result Image");

    int image_width = image.width();
    int image_height = image.height();
    float point_size = sqrt(image_width*image_height)/10;

    if (resultImageInfo.prType == PrType::Circle_Edge_Template_Matching)
    {
        qInfo("Circle_Edge_Template_Matching");
        avl::Image image1;
        avl::Image image2;
        avl::Image image3;
        avl::Image image4;

        avl::Point2D point2D1;
        avl::Point2D point2D2;

        point2D1 = avl::Point2D((int)resultImageInfo.result_x, (int)resultImageInfo.result_y);
        point2D2 = avl::Point2D((int)resultImageInfo.result_ori_x, (int)resultImageInfo.result_ori_y);

        avl::Circle2D circle2D2;

        avl::CreateCircle( point2D1, avl::Anchor2D::MiddleCenter, (float)resultImageInfo.radius, circle2D2);

        if (image.depth() != 8)
            image = image.convertToFormat(QImage::Format_RGB888);
        avl::Image imageInput(image.width(), image.height(), image.bytesPerLine(), avl::PlainType::Type::UInt8, image.depth()/8, image.bits());
        avl::RealignImagePitch(imageInput, image1);

        avs::DrawCircles_SingleColor( image1, atl::ToArray< atl::Conditional< avl::Circle2D > >(circle2D2), atl::NIL, avl::Pixel(255.0f, 255.0f, 0.0f, 0.0f), avl::DrawingStyle(avl::DrawingMode::HighQuality, 1.0f, 1.0f, false, atl::NIL, 1.0f), true, image2 );
        avs::DrawPoints_SingleColor( image2, atl::ToArray< atl::Conditional< avl::Point2D > >(point2D1), atl::NIL, avl::Pixel(255.0f, 128.0f, 0.0f, 0.0f), avl::DrawingStyle(avl::DrawingMode::HighQuality, 1.0f, 5.0f, false, avl::PointShape::Cross, point_size), true, image3 );

        QImage testImage((uchar*)image3.Data(), image3.Width(), image3.Height(), image3.Pitch(), QImage::Format_RGB888);
        image = testImage.copy();
    } else {

        atl::Array< atl::Conditional< atl::String > > g_constData2;
        g_constData2.Reset(1);
        g_constData2[0] = resultImageInfo.resultString.toStdString().c_str();
        atl::Array< atl::Conditional< avl::Location > > g_constData3;

        g_constData3.Reset(1);
        g_constData3[0] = avl::Location(0, 0);
        avl::Rectangle2D rectangle2D1;
        avl::Point2D point2D1;
        avl::Point2D point2D2;
        avl::Image image1;
        avl::Image image2;
        avl::Image image3;
        avl::Image image4;
        avl::Image image5;
        if (image.depth() != 8)
            image = image.convertToFormat(QImage::Format_RGB888);
        avl::Image imageInput(image.width(), image.height(), image.bytesPerLine(), avl::PlainType::Type::UInt8, image.depth()/8, image.bits());
        avl::RealignImagePitch(imageInput, image1);
        avl::CreateRectangle( avl::Point2D((int)resultImageInfo.rect_x, (int)resultImageInfo.rect_y), avl::Anchor2D::TopLeft, resultImageInfo.rect_angle, resultImageInfo.rect_width, resultImageInfo.rect_height, rectangle2D1 );
        point2D1 = avl::Point2D((int)resultImageInfo.result_x, (int)resultImageInfo.result_y);
        point2D2 = avl::Point2D((int)resultImageInfo.result_ori_x, (int)resultImageInfo.result_ori_y);
        avs::DrawRectangles_SingleColor( image1, atl::ToArray< atl::Conditional< avl::Rectangle2D > >(rectangle2D1), atl::NIL, avl::Pixel(255.0f, 1.0f, 255.0f, 0.0f), avl::DrawingStyle(avl::DrawingMode::HighQuality, 1.0f, 9.0f, false, atl::NIL, 1.0f), true, image2 );
        avs::DrawPoints_SingleColor( image2, atl::ToArray< atl::Conditional< avl::Point2D > >(point2D1), atl::NIL, avl::Pixel(255.0f, 128.0f, 0.0f, 0.0f), avl::DrawingStyle(avl::DrawingMode::HighQuality, 1.0f, 10.0f, false, avl::PointShape::Cross, point_size), true, image3 );
        avs::DrawPoints_SingleColor( image3, atl::ToArray< atl::Conditional< avl::Point2D > >(point2D2), atl::NIL, avl::Pixel(0.0f, 255.0f, 0.0f, 0.0f), avl::DrawingStyle(avl::DrawingMode::HighQuality, 1.0f, 10.0f, false, avl::PointShape::Cross, point_size), true, image4 );
        avs::DrawStrings_SingleColor( image4, g_constData2, g_constData3, atl::NIL, avl::Anchor2D::TopLeft, avl::Pixel(0.0f, 255.0f, 0.0f, 0.0f), avl::DrawingStyle(avl::DrawingMode::HighQuality, 1.0f, 1.0f, false, atl::NIL, point_size), point_size, 0.0f, true, atl::NIL, image5 );
        QImage testImage((uchar*)image5.Data(), image5.Width(), image5.Height(), image5.Pitch(), QImage::Format_RGB888);
        image = testImage.copy();
    }

}
